package com.coolwar.design.proxy.dynamic.mybatis;

import com.coolwar.common.JsonConvert;

import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class MapperMethod {

    private final String sqlId;
    private final Method method;

    public MapperMethod(String sqlId, Method method) {
        this.sqlId = sqlId;
        this.method = method;
    }

    public Object execute(SqlSession sqlSession, Object[] args) {
        Map<String, String> mapperConfiguration = sqlSession.getMapperConfiguration();
        String sql = mapperConfiguration.get(sqlId);
        Object result;
        if (sql.contains("insert")) {
            result = sqlSession.insert(sql, args);
        } else if (sql.contains("update")) {
            result = sqlSession.update(sql, args);
        } else if (sql.contains("delete")) {
            result = sqlSession.delete(sql, args);
        } else if (sql.contains("select")) {
            Class<?> returnType = method.getReturnType();
            if (returnType.isArray() || returnType.getName().endsWith(".List") || returnType.getName().endsWith(".Set")) {
                result = executeForMany(sqlSession, sql, args);
            } else {
                result = JsonConvert.toObject(JsonConvert.toJson(sqlSession.select(sql, args)), returnType);
            }
        } else {
            throw new RuntimeException("Unknown execution method for: " + sqlId);
        }
        for (Object arg : args) {
            System.out.println("参数：" + arg);
        }
        return result;
    }

    private <E> Object executeForMany(SqlSession sqlSession, String sql, Object[] args) {
        List<E> result;
        result = sqlSession.selectList(sql, args);
        List<Object> list = new ArrayList<>();
        Class<?> aClass = (Class) ((ParameterizedType) method.getGenericReturnType()).getActualTypeArguments()[0];
        for (E e : result) {
            list.add(JsonConvert.toObject(JsonConvert.toJson(e), aClass));
        }
        return list;
    }

    @SuppressWarnings("unchecked")
    private <E> E[] convertToArray(List<E> list) {
        E[] array = (E[]) Array.newInstance(method.getReturnType().getComponentType(), list.size());
        array = list.toArray(array);
        return array;
    }

}
